# -*- coding: utf-8 -*-
'''
@文件    :client.py
@说明    :
@时间    :2025/06/13 16:27:13
@作者    :浪晋
@版本    :1.0
'''


import hashlib
import json
import random
import requests
from collections import OrderedDict
from Crypto.PublicKey import RSA
from Crypto.Hash import MD5, SHA1, SHA256
from Crypto.Signature import PKCS1_v1_5 as Signature_PKC
import base64
from io import BytesIO
from requests_toolbelt.multipart.encoder import MultipartEncoder
from loguru import logger
from . import utils
from . import config

# 构建post请求
class AsignClient:
    def __init__(self, notify_url, base_url=None, appId=None, appKey=None):
        """爱签API客户端"""
        self.notify_url = notify_url
        self.base_url = base_url or config.base_url
        self.appId = appId or config.appId
        self.appKey = appKey or config.private_key # 私钥
        
        
    
    def _generate_request_sign(self, jsonstr, timestamp):
        """生成请求签名"""
        # 按照阿拉伯字符排序
        data = dict()
        data["appId"] = self.appId
        data["timestamp"] = timestamp
        data["bizData"] = jsonstr

        # 计算md5值
        m = hashlib.md5()
        m.update(jsonstr.encode('utf-8'))
        # 二进制数据字符串值
        md5_str = m.hexdigest()
        sign_str = '%s%s%s%s' % (jsonstr, md5_str, self.appId, timestamp)
        # 打印签名值
        private_keyBytes = base64.b64decode(self.appKey)
        rsakey = RSA.importKey(private_keyBytes)
        signer = Signature_PKC.new(rsakey)
        # 根据SHA256算法处理签名内容data
        sha_data = SHA1.new(sign_str.encode("utf-8"))
        # 私钥进行签名
        signature = base64.b64encode(signer.sign(sha_data))
        return signature

    def _request(self, path, reqBodyData, file_bytes=None, file_key=None, file_name=None):
        """请求通用方法"""
                
        url = self.base_url + path
        accept = "*/*"
        contentType = "multipart/form-data; charset=UTF-8"
        timestamp = utils.generate_timestamp()
        jsonstr = json.dumps(reqBodyData, sort_keys=True, separators=(',', ':'), ensure_ascii=False)
        if (file_bytes != None):
            m = MultipartEncoder(
                fields={
                    'appId': self.appId,
                    'bizData': jsonstr,
                    'timestamp': timestamp,
                    'Content-Type': 'application/octet-stream',
                    'type': 'application/octet-stream',
                    # 'templateFile': ('templateFile.pdf', open('/ac/project/python/file/b.pdf', 'rb'), 'application/octet-stream')
                    file_key: (file_name, BytesIO(file_bytes), 'application/octet-stream')
                },
                boundary='-----------------------------' + str(random.randint(int(1e28), int(1e29 - 1))))
        else:
            m = MultipartEncoder(
                fields={
                    'appId': self.appId,
                    'bizData': jsonstr,
                    'timestamp': timestamp,
                    'Content-Type': 'application/octet-stream',
                    'type': 'application/octet-stream'
                },
                boundary='-----------------------------' + str(random.randint(int(1e28), int(1e29 - 1))))

        
        # 构建请求头
        headers = {
            'Content-Type': contentType,
            'Accept': accept,
            'sign': self._generate_request_sign(jsonstr, timestamp)
        }
        headers['Content-Type'] = m.content_type
        logger.info(f"爱签请求参数: {headers}")
        logger.info(f"爱签请求参数: {m}")
        r = requests.post(url, data=m, headers=headers)
        logger.info(f"爱签响应结果: {r.text}")
        return r.json()

    def uploadFileByUrl(self, fileurl, filename, extension,fileType=3):
        """通过网络文件地址上传"""
        url = "/upload/file/by/url"
        reqBodyData = {
            "fileurl": fileurl,
            "filename":filename,
            "extension": extension,
            "fileType": fileType
        }
        result = self._request(url, reqBodyData)
        return result



    def templateList(self):
        """查询模板列表"""
        url = "/template/list"
        reqBodyData = {}
        result = self._request(url, reqBodyData)
        return result

    def uploadTemplate(self,file_bytes, file_name):
        """本地模板上传"""
        _timestamp = utils.generate_timestamp()
        template_no = "t_" + _timestamp
        reqBodyData = {"templateName": file_name, "templateNo": template_no}
        url = "/contract/uploadTemplate"
        file_key = 'templateFile'
        result = self._request(url, reqBodyData, file_bytes, file_key, file_name)
        return result


    def embedUploadTemplate(self,file_name, file_bytes=None, fileId=None):
        """嵌入式模板文件上传"""
        url = "/template/upload"
        template_no = utils.generate_order_no("Template")
        reqBodyData = {"templateIdent": template_no, "isCover": 1}
        if fileId:
            reqBodyData.update(fileId=fileId)
            result = self._request(url, reqBodyData)
        else:
            file_key = 'file'
            result = self._request(url, reqBodyData, file_bytes, file_key, file_name)
        return result

    def embedOpenTemplate(self, template_no):
        """新增/编辑模板"""
        url = "/template/open"
        reqBodyData = {
            "templateIdent": template_no, 
            "notifyUrl": self.notify_url,
            "isControlDelete": 1,
            "controlData":[
                {"dataType": 1, "dataKey": "订购单号", "needDrag": 0},
                {"dataType": 1, "dataKey": "产品名", "needDrag": 0},
                {"dataType": 1, "dataKey": "实付金额", "needDrag": 0},
                {"dataType": 1, "dataKey": "总期数", "needDrag": 0},
                {"dataType": 1, "dataKey": "用户姓名", "needDrag": 0},
                {"dataType": 1, "dataKey": "用户手机号", "needDrag": 0},
                {"dataType": 1, "dataKey": "用户身份证号", "needDrag": 0},
                {"dataType": 1, "dataKey": "每期金额", "needDrag": 0}
            ]
        }
        result = self._request(url, reqBodyData)
        return result
    
    def embedSyncTemplate(self, template_no):
        """同步模板"""
        url = "/template/sync"
        reqBodyData = {
            "templateIdent": template_no
        }
        result = self._request(url, reqBodyData)
        return result
    
    def authCompanyIdentifyUrl(self, orderNo, companyName, creditCode, legalPersonName, legalPersonIdCardNo, noticeMobile, notifyUrl):
        """企业实名认证网页版"""
        url = "/auth/company/identifyUrl"
        reqBodyData = {
            "bizId":orderNo,
            "companyName": companyName,
            "creditCode": creditCode,
            "legalPersonName": legalPersonName,
            "legalPersonIdCardNo": legalPersonIdCardNo,
            "noticeMobile": noticeMobile,
            "notifyUrl": notifyUrl,
            "isNotice": 1
        }
        result = self._request(url, reqBodyData)
        return result

    def addEnterpriseUser(self,account, serialNo):
        """添加企业用户（V2）"""
        url = "/v2/user/addEnterpriseUser"
        reqBodyData = {
            "account":account,
            "serialNo":serialNo
        }
        result = self._request(url, reqBodyData)
        return result

    def modifyCompanyInfo(self,account, companyName=None,name=None,idCard=None,idCardType=None):
        """修改企业信息"""
        url = "/user/modifyCompanyInfo"
        reqBodyData = {
            "account":account
        }
        if companyName:
            reqBodyData.update(companyName=companyName)
        if name:
            reqBodyData.update(name=name)
        if idCard:
            reqBodyData.update(idCard=idCard)
        if idCardType:
            reqBodyData.update(idCardType=idCardType)
        result = self._request(url, reqBodyData)
        return result


    def getUserSeals(self,account):
        """获取指定用户的印章"""
        url = "/user/getUserSeals"
        reqBodyData = {
            "account":account
        }
        result = self._request(url, reqBodyData)
        return result


    def sealNocheckAuth(self,authAccount, sealNo):
        """印章授权（无校验）"""
        url = "/seal/nocheckAuth"
        reqBodyData = {
            "authAccount":authAccount,
            "sealNo":sealNo
        }
        result = self._request(url, reqBodyData)
        return result

    def sealCaptchaAuth(self, authAccount, sealNo):
        """印章授权(验证码)"""
        url = "/seal/captchaAuth"
        reqBodyData = {
            "authAccount":authAccount,
            "sealNo":sealNo
        }
        result = self._request(url, reqBodyData)
        return result

    def sealCaptchaAuthVerify(self, captchaId, captcha):
        """印章授权校验(验证码)"""
        url = "/seal/captchaAuthVerify"
        reqBodyData = {
            "captchaId":captchaId,
            "captcha":captcha
        }
        result = self._request(url, reqBodyData)
        return result

    def addPersonalUser(self,phone, serialNo):
        """添加个人用户（V2）"""
        url = "/v2/user/addPersonalUser"
        reqBodyData = {
            "account":phone,
            "serialNo": serialNo
        }
        result = self._request(url, reqBodyData)
        return result

    def addStranger(self,account, phone, realName, idCard, userType = 2):
        """添加陌生用户（V2）"""
        url = "/v2/user/addStranger"
        reqBodyData = {
            "account":account,
            "userType": userType,
            "mobile": phone,
            "isNotice": 1,
            "name": realName,
            "idCard": idCard,
            "immutableInfoList":["realName","mobile", "idCardNo"]
        }
        result = self._request(url, reqBodyData)
        return result

    def getUserInfo(self, account, idCard):
        """查询用户信息"""
        url = "/user/getUser"
        reqBodyData = {
            "account":account,
            "idCard": idCard
        }
        result = self._request(url, reqBodyData)
        return result


    def checkAndAddStranger(self, account, phone, realName, idCard):
        """根据用户账号判断用户状态"""
        result = self.getUserInfo(account, idCard)
        if result["code"] == 100025: # 用户不存在
            self.addStranger(account, phone, realName, idCard)
            return account, 10
        elif result["code"] == 100082:  # 用户未认证
            return account, 10
        else:
            return account, 8

    def contractByTemplateCreate(self, contractNo, contractName, templateNo, fillData, notifyUrl, callbackUrl, redirectUrl):
        """基于模板创建待签署文件"""
        url = "/contract/createContract"
        reqBodyData = {
            "contractNo": contractNo,
            "contractName":contractName,
            "validityTime": 15,
            "signOrder": 1,
            "templates":[{
                "templateNo":templateNo,
                "fillData": fillData
            }],
            "notifyUrl":notifyUrl,
            "callbackUrl": callbackUrl,
            "redirectUrl":redirectUrl
        }
        result = self._request(url, reqBodyData)
        return result
    
    def contractAddSigner(self,signer1,signer2):
        """添加签署方"""
        url = "/contract/addSigner"
        reqBodyData = [signer1, signer2]
        result = self._request(url, reqBodyData)
        return result
    
    def contractWithdraw(self,contractNo, reason=None):
        """合同撤销"""
        url = "/contract/withdraw"
        reqBodyData = {
            "contractNo":contractNo,
            "withdrawReason": reason,
            "isNoticeSignUser":True 
        }
        result = self._request(url, reqBodyData)
        return result
    
    def contractDownloadBase64(self,contractNo):
        """下载合同"""
        url = "/contract/downloadContract"
        reqBodyData = {
            "contractNo":contractNo
        }
        result = self._request(url, reqBodyData)
        return result


    def contractDownloadUrl(self,contractNo):
        """下载合同"""
        url = "/v2/contract/getContractDownloadUrl"
        reqBodyData = {
            "contractNo":contractNo
        }
        result = self._request(url, reqBodyData)
        return result